package com.turnengine.client.local.location.plugin.coordinate;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.turnengine.client.local.location.bean.Coordinate;
import com.turnengine.client.local.location.bean.CoordinateRange;
import com.turnengine.client.local.location.bean.ICoordinate;
import com.turnengine.client.local.location.bean.ICoordinateRange;
import com.turnengine.client.local.location.plugin.grid.ICoordinateGridSet;

public class LocationCoordinatePlugin implements ILocationCoordinatePlugin {

	private static final Logger log = LoggerFactory.getLogger(LocationCoordinatePlugin.class);

	private final ICoordinateGridSet gridSet;

	public LocationCoordinatePlugin(ICoordinateGridSet gridSet) {
		this.gridSet = gridSet;
	}

	@Override
	public ICoordinate getCoordinate(int locationId) {
		int locations = gridSet.getTotalLocations();
		int[] coordinates = new int[gridSet.grids()];
		int offset = locationId;
		for (int i = 0; i < gridSet.grids(); i++) {
			int locationsPerElement = locations / gridSet.getGridElements(i);
			int element = offset / locationsPerElement;

			coordinates[i] = (element + 1);
			locations = locationsPerElement;
			offset -= (element * locationsPerElement);
		}
		return new Coordinate(locationId, coordinates);
	}

	@Override
	public ICoordinate getCoordinate(int[] coordinates) {
		if (coordinates.length != gridSet.grids()) {
			throw new IllegalArgumentException("coordinates are empty");
		}
		checkValues(coordinates);
		int locationId = getStartLocationId(coordinates);
		return new Coordinate(locationId, coordinates);
	}

	private int getStartLocationId(int[] coordinates) {
		int locationId = 0;
		if (coordinates.length == 0) {
			return locationId;
		}
		int locations = gridSet.getTotalLocations();
		for (int i = 0; i < coordinates.length; i++) {
			int locationsPerElement = locations / gridSet.getGridElements(i);
			int element = coordinates[i] - 1;

			locations = locationsPerElement;
			locationId += (element * locationsPerElement);
		}
		return locationId;
	}

	private void checkValues(int[] coordinates) {
		for (int i = 0; i < coordinates.length; i++) {
			if (coordinates[i] < 1 || coordinates[i] > gridSet.getGridElements(i)) {
				throw new IllegalArgumentException("coordinates=" + Arrays.toString(coordinates));
			}
		}
	}

	@Override
	public ICoordinateRange getCoordinateRange(int[] coordinates) {
		if (coordinates.length > gridSet.grids()) {
			throw new IllegalArgumentException("coordinates.length=" + coordinates.length);
		}
		checkValues(coordinates);

		int startLocationId = getStartLocationId(coordinates);
		int finishLocationId = startLocationId + (gridSet.getGridLocations(coordinates.length - 1) - 1);

		return new CoordinateRange(startLocationId, finishLocationId);
	}
}
